﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.templates;
using l1cs.server.serverpackets;
using l1cs.server.datatables;

namespace l1cs.server.model.Instance
{
    public class L1CrownInstance : L1NpcInstance
    {
        private static Logger _log = Logger.getLogger( typeof( L1CrownInstance ).FullName );

        public L1CrownInstance( L1Npc template )
            : base( template ) { }

        override public void onAction( L1PcInstance player )
        {
            bool in_war = false;
            if ( player.getClanid() == 0 )
            { // クラン未所属
                return;
            }
            String playerClanName = player.getClanname();
            L1Clan clan = L1World.getInstance().getClan( playerClanName );
            if ( clan == null )
            {
                return;
            }
            if ( !player.isCrown() )
            { // 君主以外
                return;
            }
            if ( player.getTempCharGfx() != 0 && // 変身中
                    player.getTempCharGfx() != 1 )
            {
                return;
            }
            if ( player.getId() != clan.getLeaderId() )
            { // 血盟主以外
                return;
            }
            if ( !checkRange( player ) )
            { // クラウンの1セル以内
                return;
            }
            if ( clan.getCastleId() != 0 )
            {
                // 城主クラン
                // あなたはすでに城を所有しているので、他の城を取ることは出来ません。
                player.sendPackets( new S_ServerMessage( 474 ) );
                return;
            }

            // クラウンの座標からcastle_idを取得
            int castle_id = L1CastleLocation
                    .getCastleId( getX(), getY(), getMapId() );

            // 布告しているかチェック。但し、城主が居ない場合は布告不要
            bool existDefenseClan = false;
            L1Clan defence_clan = null;
            foreach ( L1Clan defClan in L1World.getInstance().getAllClans() )
            {
                if ( castle_id == defClan.getCastleId() )
                {
                    // 元の城主クラン
                    defence_clan = L1World.getInstance().getClan(
                            defClan.getClanName() );
                    existDefenseClan = true;
                    break;
                }
            }
            Array wars = L1World.getInstance().getWarList(); // 全戦争リストを取得
            foreach ( L1War war in wars )
            {
                if ( castle_id == war.GetCastleId() )
                { // 今居る城の戦争
                    in_war = war.CheckClanInWar( playerClanName );
                    break;
                }
            }
            if ( existDefenseClan && in_war == false )
            { // 城主が居て、布告していない場合
                return;
            }

            // clan_dataのhascastleを更新し、キャラクターにクラウンを付ける
            if ( existDefenseClan && defence_clan != null )
            { // 元の城主クランが居る
                defence_clan.setCastleId( 0 );
                ClanTable.getInstance().updateClan( defence_clan );
                L1PcInstance[] defence_clan_member = defence_clan.getOnlineClanMember();
                for ( int m = 0; m < defence_clan_member.Length; m++ )
                {
                    if ( defence_clan_member[m].getId() == defence_clan
                            .getLeaderId() )
                    { // 元の城主クランの君主
                        defence_clan_member[m].sendPackets( new S_CastleMaster( 0,
                                defence_clan_member[m].getId() ) );
                        defence_clan_member[m].broadcastPacket( new S_CastleMaster(
                                0, defence_clan_member[m].getId() ) );
                        break;
                    }
                }
            }
            clan.setCastleId( castle_id );
            ClanTable.getInstance().updateClan( clan );
            player.sendPackets( new S_CastleMaster( castle_id, player.getId() ) );
            player.broadcastPacket( new S_CastleMaster( castle_id, player.getId() ) );

            // クラン員以外を街に強制テレポート
            int[] loc = new int[3];
            foreach ( L1PcInstance pc in L1World.getInstance().getAllPlayers() )
            {
                if ( pc.getClanid() != player.getClanid() && !pc.isGm() )
                {

                    if ( L1CastleLocation.checkInWarArea( castle_id, pc ) )
                    {
                        // 旗内に居る
                        loc = L1CastleLocation.getGetBackLoc( castle_id );
                        int locx = loc[0];
                        int locy = loc[1];
                        short mapid = (short)loc[2];
                        L1Teleport.teleport( pc, locx, locy, mapid, 5, true );
                    }
                }
            }

            // メッセージ表示
            foreach ( L1War war in wars )
            {
                if ( war.CheckClanInWar( playerClanName ) && existDefenseClan )
                {
                    // 自クランが参加中で、城主が交代
                    war.WinCastleWar( playerClanName );
                    break;
                }
            }
            L1PcInstance[] clanMember = clan.getOnlineClanMember();

            if ( clanMember.Length > 0 )
            {
                // 城を占拠しました。
                S_ServerMessage s_serverMessage = new S_ServerMessage( 643 );
                foreach ( L1PcInstance pc in clanMember )
                {
                    pc.sendPackets( s_serverMessage );
                }
            }

            // クラウンを消す
            deleteMe();

            // タワーを消して再出現させる
            foreach ( L1Object l1object in L1World.getInstance().getObject() )
            {
                if ( l1object is L1TowerInstance )
                {
                    L1TowerInstance tower = (L1TowerInstance)l1object;
                    if ( L1CastleLocation.checkInWarArea( castle_id, tower ) )
                    {
                        tower.deleteMe();
                    }
                }
            }
            L1WarSpawn warspawn = new L1WarSpawn();
            warspawn.SpawnTower( castle_id );

            // 城門を元に戻す
            foreach ( L1DoorInstance door in DoorSpawnTable.getInstance().getDoorList() )
            {
                if ( L1CastleLocation.checkInWarArea( castle_id, door ) )
                {
                    door.repairGate();
                }
            }
        }

        override public void deleteMe()
        {
            _destroyed = true;
            if ( getInventory() != null )
            {
                getInventory().clearItems();
            }
            allTargetClear();
            _master = null;
            L1World.getInstance().removeVisibleObject( this );
            L1World.getInstance().removeObject( this );
            foreach ( L1PcInstance pc in L1World.getInstance().getRecognizePlayer( this ) )
            {
                pc.removeKnownObject( this );
                pc.sendPackets( new S_RemoveObject( this ) );
            }
            removeAllKnownObjects();
        }

        private bool checkRange( L1PcInstance pc )
        {
            return ( getX() - 1 <= pc.getX() && pc.getX() <= getX() + 1
                    && getY() - 1 <= pc.getY() && pc.getY() <= getY() + 1 );
        }
    }
}
